#include <sys/time.h>
#include <stdint.h>
#include <sys/types.h>
#include <unistd.h> 
#include <stdlib.h>
#include <assert.h>
#include "app_platform/cntl_info.h"
#include "giserpdao.h"

#include "c2cplatform/component/dal/dal_set.h"
#include "c2cplatform/component/dal/db_operator_mysql_set.h"

using namespace c2cplatform::component::dal;
using namespace c2cent::storage;

using namespace erp::gis::dao;

CPP_SELF_DEFINE_START
/**
*  请在这里增加自定义的成员变量和函数及其他内容，否则无法合并代码
**/
#include "giserpdao_enum.h"

#include "libc2c/c2c_errno_define.h"
#include "erp/comm/erp_macro_define.h"
#include "erp/comm/erp_cache_client.h"
#include "erp/comm/erp_errno_define.h"

using namespace c2cent::library::wwlog;
using namespace c2cent::library::wtimeelf;
using namespace erp::comm;

c2cent::library::wtimeelf::CItilGroup CGisErpDao::m_oShipTypeAreaLocusRowSync(ITIL_SHIPTYPEAREALOCUS_ROW_SYNC_REQ, ITIL_SHIPTYPEAREALOCUS_ROW_SYNC_ERR, ITIL_SHIPTYPEAREALOCUS_ROW_SYNC_RSP, ITIL_SHIPTYPEAREALOCUS_ROW_SYNC_DEF,c2cent::library::wtimeelf::TIME_50MS);
c2cent::library::wtimeelf::CItilGroup CGisErpDao::m_oGetMapCoverLocusList(ITIL_GET_MAPCOVERLOCUS_LIST_REQ, ITIL_GET_MAPCOVERLOCUS_LIST_ERR, ITIL_GET_MAPCOVERLOCUS_LIST_RSP, ITIL_GET_MAPCOVERLOCUS_LIST_DEF,c2cent::library::wtimeelf::TIME_50MS);

uint32_t CGisErpDao::m_dwTmemBid;
uint32_t CGisErpDao::m_dwMaxRecordNumPerArea; 
std::string CGisErpDao::m_strDBRole; 
std::string CGisErpDao::m_strShipAreaLocusTable; 

#define CONNECT_WITH_DAL(CmdId, SubAccountId, TableName, UseSetId) c2cplatform::component::dal::IDBOperator* pIDB = CDAL_SET->GetDBOperator(CmdId, SubAccountId, m_strDBRole , TableName, UseSetId);\
    if(pIDB == NULL)\
    {\
        C2C_WW_LOG_ERR(ERR_DB_DBOPR, "CDAL_SET->GetDBOperator() failed, CmdId:%u CooperatorId:%u \
                        RoleName:%s TableName:%s UseSetId:%u ErrMsg:%s", \
                        CmdId, SubAccountId, DAO_GIS_ERP_ROLE_NAME, TableName.c_str(), UseSetId, CDAL_SET->getLastErrMsg()); \
        return ERR_DB_DBOPR;\
    }\
    c2cent::storage::CMySqlStorage oStorage(pIDB)

static void ItilAlarm(const std::string& strAlarmMsg)
{
	char sAlarmMsg[256] = {0};
	snprintf(sAlarmMsg, sizeof(sAlarmMsg), "%s", strAlarmMsg.c_str());
	adv_attr_set2(ITIL_DAO_GIS_ERP_ALARM, sizeof(sAlarmMsg), sAlarmMsg);
}


uint32_t CGisErpDao::_GetMapCoverLocusListFromDB(
     const CCntlInfo& rCntlInfo,
     uint32_t dwShipType,
     uint32_t dwDestGbId,
     C2C_TIME_ELF_ITIL& oWTimeElf,
     erp::gis::ddo::CShipTypeAreaLocusDoList& oShipTypeAreaLocusDoList,
     std::string& strErrMsg
     )
{
	uint32_t dwRet = 0;
	CONNECT_WITH_DAL(rCntlInfo.getCmdId(), rCntlInfo.getOperatorUin(), m_strShipAreaLocusTable , m_wUseSetId);

    std::stringstream sql;
	dwRet = _GenerateGetMapCoverLocusListSql(dwShipType, dwDestGbId, sql);
    if(dwRet != 0)
    {
        C2C_WW_LOG_ERR(dwRet, "Generate Sql Failed. Maybe dwShipType and dwDestGbId invalid.");
        return dwRet;
    }

    c2cent::storage::IResultSet& oRs = oStorage.QueryForResultSet(sql.str());
    oWTimeElf.AddTimeMark("oStorage.QueryForResultSet", dwRet);

    if( !oRs.IsReady())
    {
        C2C_WW_LOG_ERR(ERR_DB_DBOPR, "QueryMapCoverLocusListFromDB Failed ,ErrMsg: %s", oStorage.GetErrMsg());
        return ERR_DB_DBOPR;
    }

    if(oRs.First() && oRs.GetRecordCount() > 0)
    {

        do{
            erp::gis::ddo::CShipTypeAreaLocusDo oShipTypeAreaLocusDo;
            _AssignShipTypeAreaLocusDo(oShipTypeAreaLocusDo, oRs);

            std::stringstream sstr;
            oShipTypeAreaLocusDo.DumpData(sstr);
            C2C_WW_LOG_DEBUG("oShipTypeAreaLocusDo:%s", sstr.str().c_str());

            oShipTypeAreaLocusDoList.vecShipTypeAreaLocusDo.push_back(oShipTypeAreaLocusDo);
        }while(oRs.Next());
    }
    else
    {
        //oRs.Close();
        C2C_WW_LOG("QueryMapCoverLocusListFromDB Failed! DB ResultSet Empty. ShipType:%u GbAreaId:%u sql:%s ",dwShipType, dwDestGbId, sql.str().c_str() );
        //不return 结果集为空也要建cache
    }

    //oRs.Close();
    //建cache
    uint32_t dwCurrentTime =(uint32_t) time(0);
    dwRet = TMEM_CACHE_OP->AddSimpleData(_GetTmemKey(dwShipType, dwDestGbId),oShipTypeAreaLocusDoList,dwCurrentTime);

    oWTimeElf.AddTimeMark("TMEM_CACHE_OP->AddSimpleData", dwRet);
    if(dwRet != 0)
    {
        strErrMsg += "ShipTypeAreaLocusRowSync TMEM AddSimpleData failed!";
        strErrMsg += TMEM_CACHE_OP->GetLastErrMsg();
        ItilAlarm(strErrMsg);

        C2C_WW_LOG_ERR(dwRet, "ShipTypeAreaLocusRowSync TMEM AddSimpleData failed!  ShipType[%u] GbAreaId[%u] DBRole[%s] DBTable[%s] ErrMsg[%s]",
                       dwShipType, dwDestGbId , DAO_GIS_ERP_ROLE_NAME, GIS_TABLE_SHIPTYPE_AREA_LOCUS, strErrMsg.c_str());
    }
    
    C2C_WW_LOG("ShipTypeAreaLocusRowSync TMEM success ! %s dwCurrentTime: %u", _GetTmemKey(dwShipType, dwDestGbId).c_str(), dwCurrentTime);
	return dwRet;
}

uint32_t CGisErpDao::_GetShipTypeAreaLocusRowCountInDB(
    const CCntlInfo& rCntlInfo,
    const erp::gis::ddo::CShipTypeAreaLocusDo& oShipTypeAreaLocusDo,
    uint32_t& dwRecordCount,
    std::string& strErrMsg
    )
{
    uint32_t dwRet = 0;
    std::stringstream sql;
    _GenerateGetShipTypeAreaLocusRecordCountSql(oShipTypeAreaLocusDo.GetShipType(), oShipTypeAreaLocusDo.GetShipTypeLocusGbAreaid(),sql);
	CONNECT_WITH_DAL(rCntlInfo.getCmdId(), rCntlInfo.getOperatorUin(), m_strShipAreaLocusTable , m_wUseSetId);

    c2cent::storage::IResultSet& oRs = oStorage.QueryForResultSet(sql.str());
    if( !oRs.IsReady())
    {
        C2C_WW_LOG_ERR(ERR_DB_DBOPR, "QueryShipTypeAreaLocusRowCountInDB Failed ,ErrMsg: %s", oStorage.GetErrMsg());
        return ERR_DB_DBOPR;
    }

    if(oRs.First() && oRs.GetRecordCount() > 0)
    {
        dwRecordCount = oRs.GetBigUInt("count(1)");
    }
    else
    {
      //oRs.Close();
        C2C_WW_LOG("QueryShipTypeAreaLocusRowCountInDB Failed! ResultSet is Empty. Sql:%s ", sql.str().c_str());
        return dwRet;
    }

    //oRs.Close();
    return dwRet;
}

bool CGisErpDao::IsShipTypeAreaLocusRowExist(
    const CCntlInfo& rCntlInfo,
    const erp::gis::ddo::CShipTypeAreaLocusDo& oShipTypeAreaLocusDo,
    std::string& strErrMsg
    )
{
    uint32_t dwRet = 0;
    std::stringstream sql;
    
    sql << "Select * From "
        << CDAL_SET->GetTableName(m_wUseSetId, 0 ,DAO_GIS_ERP_ROLE_NAME, GIS_TABLE_SHIPTYPE_AREA_LOCUS)
        << " Where FSysNo =" << oShipTypeAreaLocusDo.GetRecordSysNo()
        << ";";

	CONNECT_WITH_DAL(rCntlInfo.getCmdId(),rCntlInfo.getOperatorUin(), m_strShipAreaLocusTable , m_wUseSetId);
    c2cent::storage::IResultSet& oRs = oStorage.QueryForResultSet(sql.str());
    if( !oRs.IsReady())
    {
        strErrMsg = "QueryShipTypeAreaLocusRowCountInDB Failed ,ErrMsg: ";
        strErrMsg += oStorage.GetErrMsg();
        return false;
    }

    if(oRs.First() && oRs.GetRecordCount() > 0)
    {
        oRs.Close();
        return true;
    }
    else
    {
        oRs.Close();
        return false;
    }
}


uint32_t CGisErpDao::_UpdateShipTypeAreaLocusRowInDB(
    const CCntlInfo& rCntlInfo,
    const erp::gis::ddo::CShipTypeAreaLocusDo& oShipTypeAreaLocusDo,
    std::string& strErrMsg
    )
{
    uint32_t dwRet = 0;
	CONNECT_WITH_DAL(rCntlInfo.getCmdId(),rCntlInfo.getOperatorUin(), m_strShipAreaLocusTable , m_wUseSetId);
    std::stringstream sql;
	dwRet = _GenerateUpdateShipTypeAreaLocusRowSql(oShipTypeAreaLocusDo, sql, oStorage);
    
    if(dwRet != 0)
    {
        C2C_WW_LOG_ERR(dwRet,"Generate Sql Failed.");
        return dwRet;
    }

	dwRet = oStorage.Update(sql.str());

	if (dwRet != 0)
	{	
		if (oStorage.GetErrno() == 1062)//Duplicate entry主键重复或唯一索引重复，返回记录已存在的错误码
		{
            C2C_WW_LOG_ERR(ERR_DB_KEY_EXIST, "Replace ShipTypeAreaLocusRow Failed, Key Exist . DB errMsg: %s",oStorage.GetErrMsg());
            return ERR_DB_KEY_EXIST; 
		}
        else
		{
			strErrMsg = "Update ShipTypeAreaLocusRow Failed DB errMsg: ";
            C2C_WW_LOG_ERR(dwRet, "Update ShipTypeAreaLocusRow Failed DB errMsg: %s", oStorage.GetErrMsg());
		    return dwRet;
		}
	}

    return dwRet;
}


uint32_t CGisErpDao::_GenerateUpdateShipTypeAreaLocusRowSql(
     const erp::gis::ddo::CShipTypeAreaLocusDo& oShipTypeAreaLocusDo,
     std::stringstream& sql,
     c2cent::storage::CMySqlStorage& oStorage
     )
{
	sql << "REPLACE INTO "
        << CDAL_SET->GetTableName(m_wUseSetId, 0 ,DAO_GIS_ERP_ROLE_NAME, GIS_TABLE_SHIPTYPE_AREA_LOCUS)
        << " Set FSysNo = " << oShipTypeAreaLocusDo.GetRecordSysNo();

    if(oShipTypeAreaLocusDo.IsShipTypeSet())
    {
        sql << ", FShipType = " << oShipTypeAreaLocusDo.GetShipType();
    }
        
    if(oShipTypeAreaLocusDo.IsShipTypeLocusGbAreaidSet())
    {
        sql << ", FGbAreaid = " << oShipTypeAreaLocusDo.GetShipTypeLocusGbAreaid();
    }
    
    if(oShipTypeAreaLocusDo.IsBranchSysNoSet())
    {
        sql << ", FBranchSysNo = " << oShipTypeAreaLocusDo.GetBranchSysNo();
    }

    if(oShipTypeAreaLocusDo.IsShipTypeCoverLocusSet())
    {
        sql << ", FCoverLocus = '" << oStorage.EscapeString(oShipTypeAreaLocusDo.GetShipTypeCoverLocus()) << "'";
    }

    if(oShipTypeAreaLocusDo.IsStatusSet())
    {
        sql << ", FStatus = " << oShipTypeAreaLocusDo.GetStatus();
    }

    if(oShipTypeAreaLocusDo.IsCreateTimeSet())
    {
        sql << ", FRowCreateDate = FROM_UNIXTIME(" << oShipTypeAreaLocusDo.GetCreateTime() << ")";
    }

    if(oShipTypeAreaLocusDo.IsLastModifyTimeSet())
    {
        sql << ", FRowModifyDate = FROM_UNIXTIME(" << oShipTypeAreaLocusDo.GetLastModifyTime() << ")";
    }

    sql << ";";
    C2C_WW_LOG_DEBUG("Sql: %s", sql.str().c_str());
    return 0;
}

void CGisErpDao::_AssignShipTypeAreaLocusDo(
     erp::gis::ddo::CShipTypeAreaLocusDo& oShipTypeAreaLocusDo,
     c2cent::storage::IResultSet& oRs 
     )
{
    oShipTypeAreaLocusDo.SetRecordSysNo(oRs.GetUInt("Fsysno")); 
    oShipTypeAreaLocusDo.SetShipType(oRs.GetUInt("FShipType")); 
    oShipTypeAreaLocusDo.SetShipTypeLocusGbAreaid(oRs.GetUInt("FGbAreaid")); 
    oShipTypeAreaLocusDo.SetBranchSysNo(oRs.GetUInt("FBranchSysNo")); 
    oShipTypeAreaLocusDo.SetShipTypeCoverLocus(oRs.GetString("FCoverLocus")); 
    oShipTypeAreaLocusDo.SetStatus(oRs.GetUInt("FStatus")); 
    oShipTypeAreaLocusDo.SetCreateTime(oRs.GetUInt("UNIX_TIMESTAMP(FRowCreateDate)")); 
    oShipTypeAreaLocusDo.SetLastModifyTime(oRs.GetUInt("UNIX_TIMESTAMP(FRowModifyDate)")); 
}

uint32_t CGisErpDao::_GenerateGetMapCoverLocusListSql(
     uint32_t dwShipType,
     uint32_t dwDestGbId,
     std::stringstream& sql
     )
{
    sql << "Select "
        << "FSysNo,"
        << "FShipType,"
        << "FGbAreaId,"
        << "FBranchSysNo,"
        << "FCoverLocus,"
        << "FStatus,"
        << "FRowCreateDate,"
        << "FRowModifyDate "
        << "From "
        << CDAL_SET->GetTableName(m_wUseSetId, 0 ,DAO_GIS_ERP_ROLE_NAME, GIS_TABLE_SHIPTYPE_AREA_LOCUS)
        << " where FShipType=" << dwShipType
        << " and FGbAreaid=" << dwDestGbId
        << " and FStatus=0"//有效数据
        << " Limit 0," << m_dwMaxRecordNumPerArea;
    sql << ";";
    C2C_WW_LOG_DEBUG("GetMapCoverLocusListSql: %s", sql.str().c_str());
    return 0;
    
}

uint32_t CGisErpDao::_GenerateGetShipTypeAreaLocusRecordCountSql(
     uint32_t dwShipType,
     uint32_t dwDestGbId,
     std::stringstream& sql
     )
{
    sql << "Select "
        << "Count(1) "
        << "From "
        << CDAL_SET->GetTableName(m_wUseSetId, 0 ,DAO_GIS_ERP_ROLE_NAME, GIS_TABLE_SHIPTYPE_AREA_LOCUS)
        << " where FShipType=" << dwShipType
        << " and FGbAreaid=" << dwDestGbId
        << " and FStatus=0" ;//有效数据
    sql << ";";
    C2C_WW_LOG_DEBUG("GetMapCoverLocusListSql: %s", sql.str().c_str());
    return 0;
    
}
int CGisErpDao::_InitTmem(IUserDefineCntl* pCntl)
{
    int iRet = 0;
	std::string strTmemSvrName ="erp_gis_tmem";
	uint32_t dwTmemBid = 100191;//测试环境的bid
	std::map<TmemCacheItilEnum, uint32_t> mapTmemItil;
	uint64_t dwTmemExpireTime = SECONDS_ONE_DAY * 7; //默认7天
	uint32_t dwTmemReadSlowTime = TMEMCACHE_DEF_SLOW_TIME;
	uint32_t dwTmemBatchReadSlowTime = TMEMCACHE_DEF_SLOW_TIME;
	uint32_t dwTmemWriteSlowTime = TMEMCACHE_DEF_SLOW_TIME;
	uint32_t dwTmemBufferSize = TMEMCACHE_BUFFER_SIZE;
	uint32_t dwTmemUpdateAddrThreshold = TMEMCACHE_UPDATEADDR_THREDHOLD;
	bool bTmemUserNoKey=true;
	bool bTmemClosedCache=false;
	uint32_t dwTmemReadTimeout=TMEMCACHE_READ_TIMEOUT; //ms 其他cmem的是秒
	uint32_t dwTmemFailedFreezeTime=TMEMCACHE_FAILED_FREEZE_TIME;
	uint32_t dwTmemConnectTimeout=TMEMCACHE_CONNECT_TIMEOUT;

	GetStringConfig(TmemSvrName);
	GetUintConfig(TmemBid);
	GetUintConfig(TmemExpireTime);
	GetUintConfig(TmemReadSlowTime);
	GetUintConfig(TmemBatchReadSlowTime);
	GetUintConfig(TmemWriteSlowTime);
	GetUintConfig(TmemBufferSize);
	GetUintConfig(TmemUpdateAddrThreshold);

	m_dwTmemBid = dwTmemBid;

	uint32_t dwTmemUserNoKey = 1;
	GetUintConfig(TmemUserNoKey);
	if(dwTmemUserNoKey != 0)
	{
		bTmemUserNoKey = true;
	}
	else
	{
		bTmemUserNoKey = false;
	}

	uint32_t dwTmemClosedCache = 0;
	GetUintConfig(TmemClosedCache);
	if(dwTmemClosedCache != 0)
	{
		bTmemClosedCache = true;
	}
	else
	{
		bTmemClosedCache = false;
	}

	GetUintConfig(TmemReadTimeout);
	GetUintConfig(TmemFailedFreezeTime);
	GetUintConfig(TmemConnectTimeout);

	uint32_t dwTmemWriteSlowItil = ITIL_DAO_GIS_TMEM_CACHE_WRITESLOW;
	uint32_t dwTmemReadSlowItil = ITIL_DAO_GIS_TMEM_CACHE_READSLOW;
	uint32_t dwTmemBatchReadSlowItil = 0;
	uint32_t dwTmemWriteErrorItil = ITIL_DAO_GIS_TMEM_CACHE_WRITEERROR;
	uint32_t dwTmemReadErrorItil = ITIL_DAO_GIS_TMEM_CACHE_READERROR;
	uint32_t dwTmemBatchReadErrorItil = 0;
	uint32_t dwTmemWriteRequestItil = ITIL_DAO_GIS_TMEM_CACHE_WRITEREQ;
	uint32_t dwTmemReadRequestItil = ITIL_DAO_GIS_TMEM_CACHE_READREQ;
	uint32_t dwTmemBatchReadRequestItil = 0;
	uint32_t dwTmemBatchReadCellRequestItil = 0;
	uint32_t dwTmemReadHitItil = ITIL_DAO_GIS_TMEM_CACHE_READHIT;
	uint32_t dwTmemBatchReadCellHitItil = 0;

	GetUintConfig(TmemWriteSlowItil);
	GetUintConfig(TmemReadSlowItil);
	GetUintConfig(TmemBatchReadSlowItil);
	GetUintConfig(TmemWriteErrorItil);
	GetUintConfig(TmemReadErrorItil);
	GetUintConfig(TmemBatchReadErrorItil);
	GetUintConfig(TmemWriteRequestItil);
	GetUintConfig(TmemReadRequestItil);
	GetUintConfig(TmemBatchReadRequestItil);
	GetUintConfig(TmemBatchReadCellRequestItil);
	GetUintConfig(TmemReadHitItil);
	GetUintConfig(TmemBatchReadCellHitItil);

	mapTmemItil.insert(std::map<TmemCacheItilEnum, uint32_t>::value_type(ITIL_WRITE_SLOW,  dwTmemWriteSlowItil));
	mapTmemItil.insert(std::map<TmemCacheItilEnum, uint32_t>::value_type(ITIL_READ_SLOW, dwTmemReadSlowItil));
	mapTmemItil.insert(std::map<TmemCacheItilEnum, uint32_t>::value_type(ITIL_BATCHREAD_SLOW, dwTmemBatchReadSlowItil));
	mapTmemItil.insert(std::map<TmemCacheItilEnum, uint32_t>::value_type(ITIL_WRITE_ERR,  dwTmemWriteErrorItil));
	mapTmemItil.insert(std::map<TmemCacheItilEnum, uint32_t>::value_type(ITIL_READ_ERR, dwTmemReadErrorItil));
	mapTmemItil.insert(std::map<TmemCacheItilEnum, uint32_t>::value_type(ITIL_BATCHREAD_ERR, dwTmemBatchReadErrorItil));
	mapTmemItil.insert(std::map<TmemCacheItilEnum, uint32_t>::value_type(ITIL_WRITE_REQ,  dwTmemWriteRequestItil));
	mapTmemItil.insert(std::map<TmemCacheItilEnum, uint32_t>::value_type(ITIL_READ_REQ, dwTmemReadRequestItil));
	mapTmemItil.insert(std::map<TmemCacheItilEnum, uint32_t>::value_type(ITIL_BATCHREAD_REQ, dwTmemBatchReadRequestItil));
	mapTmemItil.insert(std::map<TmemCacheItilEnum, uint32_t>::value_type(ITIL_BATCHREAD_CELL_REQ, dwTmemBatchReadCellRequestItil));
	mapTmemItil.insert(std::map<TmemCacheItilEnum, uint32_t>::value_type(ITIL_READ_HIT, dwTmemReadHitItil));
	mapTmemItil.insert(std::map<TmemCacheItilEnum, uint32_t>::value_type(ITIL_BATCHREAD_CELL_HIT, dwTmemBatchReadCellHitItil));

    C2C_WW_LOG_DEBUG("Tmem Bid: %u", dwTmemBid);

	iRet = TMEM_CACHE_OP->Initialize(
		strTmemSvrName,
		dwTmemBid,
		mapTmemItil,
		dwTmemExpireTime,
		(uint16_t)dwTmemReadSlowTime,
		(uint16_t)dwTmemBatchReadSlowTime,
		(uint16_t)dwTmemWriteSlowTime,
		dwTmemBufferSize,
		dwTmemUpdateAddrThreshold,
		bTmemUserNoKey,
		bTmemClosedCache,
		dwTmemReadTimeout,
		dwTmemFailedFreezeTime,
		dwTmemConnectTimeout
		);

	if (0 != iRet)
	{
		std::cout << "TMEM_CACHE_OP Initialize() Failed!!" << std::endl;
		return iRet;
	}
	else
	{
		std::cout << "TMEM_CACHE_OP Initialize Success!" << std::endl;
	}

	std::cout << "start pid:" <<getpid() << "success" << " Complie Date: " << __DATE__ << " "
		<< __TIME__ << std::endl;

	C2C_WW_LOG("Init OK: pid[%d] Build[%s %s]", getpid(), __DATE__, __TIME__);

    return iRet;
}

uint32_t CGisErpDao::_CheckCommParameter(
     const CCntlInfo& rCntlInfo,
     const std::string& strMachineKey,
     const std::string& strSource,
     uint32_t dwSceneId,
     uint32_t dwShipType,
     uint32_t dwDestGbId
     )
{
	if (strSource.empty())
	{
		C2C_WW_LOG_ERR(ERR_APP_PARAM_INVALID, "strSource need set.");
		return ERR_APP_PARAM_INVALID;
	}

	if (strMachineKey.empty())
	{
		C2C_WW_LOG_ERR(ERR_APP_PARAM_INVALID, "strMachineKey need set.");
		return ERR_APP_PARAM_INVALID;
	}

    if(dwDestGbId == 0)
    {
		C2C_WW_LOG_ERR(ERR_APP_PARAM_INVALID, "dwDestGbId can't be 0.");
		return ERR_APP_PARAM_INVALID;
    }

    return 0;
}

uint32_t CGisErpDao::_CheckCommParameter(
     const CCntlInfo& rCntlInfo,
     const std::string& strMachineKey,
     const std::string& strSource,
     uint32_t dwSceneId
     )
{
	if (strSource.empty())
	{
		C2C_WW_LOG_ERR(ERR_APP_PARAM_INVALID, "strSource need set.");
		return ERR_APP_PARAM_INVALID;
	}

	if (strMachineKey.empty())
	{
		C2C_WW_LOG_ERR(ERR_APP_PARAM_INVALID, "strMachineKey need set.");
		return ERR_APP_PARAM_INVALID;
	}
    
    return 0;
}

std::string CGisErpDao::_GetTmemKey( 
     uint32_t dwShipType,
     uint32_t dwDestGbId
     )
{
    std::stringstream oss;
    oss << "gis_shiparea_locus_"
        << dwShipType
        << "_"
        << dwDestGbId;

    return oss.str();
}

uint32_t CGisErpDao::_ValidateShipTypeAreaLocusDo(
    const erp::gis::ddo::CShipTypeAreaLocusDo& oShipTypeAreaLocusDo
    )
{
    if(oShipTypeAreaLocusDo.GetShipTypeLocusGbAreaid() == 0)
    {
        C2C_WW_LOG_ERR(ERR_APP_PARAM_INVALID, "GbAreaid need be set.");
        return ERR_APP_PARAM_INVALID;
    }
    return 0;
}

CPP_SELF_DEFINE_END

/**
 *构建函数
 */
CGisErpDao::CGisErpDao(enum DeployMethod method)
{

}

/**
 *析构函数
 */
CGisErpDao::~CGisErpDao()
{

}


/**
 *每一次服务请求时，container都会调用此方法来清空数据
 */
void  CGisErpDao::Reset()
{

}


int  CGisErpDao::Initialize(IUserDefineCntl* pCntl)
{
	int iRet = 0;
	uint32_t dwLogSwitch = WLOG_OPEN|WLOG_KEY_OPEN|WLOG_ERR_OPEN;
	uint32_t dwCanLogRemote = 0;
    uint32_t dwMaxRecordNumPerArea = 100;
    std::string strLogModule(SERVICE_NAME);
    std::string strDBRole;
    std::string strShipTypeAreaLocusTable;
    m_strDBRole = DAO_GIS_ERP_ROLE_NAME;

	GetUintConfig(LogSwitch);
	GetStringConfig(LogModule);
	GetUintConfig(CanLogRemote);
	GetUintConfig(MaxRecordNumPerArea);
	GetStringConfig(DBRole);
	GetStringConfig(ShipTypeAreaLocusTable);

    m_strDBRole = strDBRole;
    m_strShipAreaLocusTable = strShipTypeAreaLocusTable;

    m_dwMaxRecordNumPerArea = dwMaxRecordNumPerArea;
	// 初始化日志
    if(dwMaxRecordNumPerArea == 0)
    {
        std::cout << "dwMaxRecordNumPerArea == 0 exit" << std::endl;
        C2C_WW_LOG_ERR(0, "dwMaxRecordNumPerArea == 0 exit"); 
        return -1;
    }
	if(  C2C_WWLOG->QuickInitForAPP2(SERVICE_NAME, B2B2CWW_LOG_APP_FILE_PATH, dwCanLogRemote, dwLogSwitch) != 0)
	{
		std::cerr << "C2C_WWLOG->QuickInitForAPP2 Failed" << std::endl;
		return -1 ;
	}

	C2C_WW_LOG("C2C_WWLOG->QuickInitForAPP2 OK!");
    
	 if(CDAL_SET->Initialize() != 0)
   {
        printf("CDAL_SET Init Failed, %s\n", CDAL_SET->getLastErrMsg());
        return -1;
   }
     
     if(_InitTmem(pCntl) != 0)
     {
         return -1;
     }

	std::cout<<"File:"<<__FILE__<<" Complie Date: "<<__DATE__<<" "<<__TIME__<<std::endl;
	return iRet;
}


/**
 *
 * 获取覆盖轨迹列表 
 *
 *@param String machineKey: 机器码，必填，对应网站cookie中的visitkey，若无则填随机值  [in]				
 *@param String source: 调用来源文件名称，必填  [in]				
 *@param uint32_t sceneId: 场景id，必填（目前填0即可）  [in]				
 *@param uint32_t shipType: 配送方式  [in]				
 *@param uint32_t destGbId: 目标地址国标ID(目前省或者市)  [in]				
 *@param String inReserve: 请求保留字段  [in]				
 *@param ShipTypeAreaLocusDoList shipTypeAreaLocusDoList: 覆盖轨迹列表 	[out]	
 *@param String errMsg: 错误信息 	[out]	
 *@param String outReserve: 请求保留字段 	[out]	
 *
 *@return  uint32_t : 0(成功) 其它失败
 *
 */
uint32_t CGisErpDao::GetMapCoverLocusList(
				const CCntlInfo& rCntlInfo,
				const std::string& strMachineKey,
				const std::string& strSource,
				uint32_t dwSceneId,
				uint32_t dwShipType,
				uint32_t dwDestGbId,
				const std::string& strInReserve,
				erp::gis::ddo::CShipTypeAreaLocusDoList& oShipTypeAreaLocusDoList,
				std::string& strErrMsg,
				std::string& strOutReserve
	)
{
	int dwRet = 0;
	C2C_WW_SIM_LOG_PL_HEAD();
	C2C_TIME_ELF_ITIL oWTimeElf(C2C_WWLOG, __FUNCTION__, &dwRet, &m_oGetMapCoverLocusList);
	C2C_WW_LOG("GetAReq %s CmdId:%u strMachineKey:%s strSource:%s dwSceneId:%u,dwshiptype:%u, dwdestgbid:%u",
				__FUNCTION__, rCntlInfo.getCmdId(), strMachineKey.c_str(), strSource.c_str(), dwSceneId, dwShipType, dwDestGbId);

    if(_CheckCommParameter(rCntlInfo,strMachineKey,strSource,dwSceneId,dwShipType,dwDestGbId) != 0)
    {
		C2C_WW_LOG_ERR(ERR_APP_PARAM_INVALID, "Parameter Invalid, CmdId:%u strMachineKey:%s strSource:%s dwSceneId:%u dwShipType:%u dwDestGbId:%u",
				rCntlInfo.getCmdId(), strMachineKey.c_str(), strSource.c_str(), dwSceneId, dwShipType, dwDestGbId);
        return ERR_APP_PARAM_INVALID;
    }

	dwRet = _GetMapCoverLocusListFromDB(rCntlInfo, dwShipType, dwDestGbId, oWTimeElf, oShipTypeAreaLocusDoList, strErrMsg);

    if(dwRet != 0)
    {
        C2C_WW_LOG_ERR(dwRet, "GetMapCoverLocusList Failed! CmdId:%u strMachineKey:%s strSource:%s dwSceneId:%u,dwshiptype:%u, dwDestGbId:%u errMsg:%s",
				 rCntlInfo.getCmdId(), strMachineKey.c_str(), strSource.c_str(), dwSceneId, dwShipType, dwDestGbId, strErrMsg.c_str());
        C2C_WW_LOG_LAST_ERR_LOG(strErrMsg);
    }

    C2C_WW_LOG("GetMapCoverLocusList Success!  CmdId:%u strMachineKey:%s strSource:%s dwSceneId:%u,dwshiptype:%u, dwDestGbId:%u ",
				 rCntlInfo.getCmdId(), strMachineKey.c_str(), strSource.c_str(), dwSceneId, dwShipType, dwDestGbId);

	return dwRet;
}

/**
 *
 * 同步配送区域轨迹记录 
 *
 *@param String machineKey: 机器码，必填，对应网站cookie中的visitkey，若无则填随机值  [in]				
 *@param String source: 调用来源文件名称，必填  [in]				
 *@param uint32_t sceneId: 场景id，必填（目前填0即可）  [in]				
 *@param ShipTypeAreaLocusDo shipTypeAreaLocusDo: 配送区域轨迹DO  [in]				
 *@param String inReserve: 请求保留字段  [in]				
 *@param String errMsg: 错误信息 	[out]	
 *@param String outReserve: 请求保留字段 	[out]	
 *
 *@return  uint32_t : 0(成功) 其它失败
 *
 */
uint32_t CGisErpDao::ShipTypeAreaLocusRowSync(
				const CCntlInfo& rCntlInfo,
				const std::string& strMachineKey,
				const std::string& strSource,
				uint32_t dwSceneId,
				const erp::gis::ddo::CShipTypeAreaLocusDo& oShipTypeAreaLocusDo,
				const std::string& strInReserve,
				std::string& strErrMsg,
				std::string& strOutReserve
	)
{
	int dwRet = 0;
	C2C_WW_SIM_LOG_PL_HEAD();
	C2C_TIME_ELF_ITIL oWTimeElf(C2C_WWLOG, __FUNCTION__, &dwRet, &m_oShipTypeAreaLocusRowSync);
	std::stringstream oss;
	oShipTypeAreaLocusDo.DumpData(oss);
	C2C_WW_LOG("GetAReq %s CmdId:%u strMachineKey:%s strSource:%s dwSceneId:%u,dumpFliter:%s",
				__FUNCTION__, rCntlInfo.getCmdId(), strMachineKey.c_str(), strSource.c_str(), dwSceneId,oss.str().c_str());

    if(_CheckCommParameter(rCntlInfo,strMachineKey,strSource,dwSceneId) != 0
            || _ValidateShipTypeAreaLocusDo(oShipTypeAreaLocusDo) != 0)
    {
		C2C_WW_LOG_ERR(ERR_APP_PARAM_INVALID, "Parameter Invalid, CmdId:%u strMachineKey:%s strSource:%s dwSceneId:%u dumpFliter:%s",
				rCntlInfo.getCmdId(), strMachineKey.c_str(), strSource.c_str(), dwSceneId, oss.str().c_str());
        return ERR_APP_PARAM_INVALID;
    }

    uint32_t dwExistRecordCount = 0;
    dwRet = _GetShipTypeAreaLocusRowCountInDB(rCntlInfo, oShipTypeAreaLocusDo, dwExistRecordCount,strErrMsg);
    if(dwRet != 0)
    {
        C2C_WW_LOG_ERR(dwRet, "_GetShipTypeAreaLocusRowCountInDB Failed! CmdId:%u strMachineKey:%s strSource:%s dwSceneId:%u,DumpFilter:%s errMsg:%s",
				 rCntlInfo.getCmdId(), strMachineKey.c_str(), strSource.c_str(), dwSceneId, oss.str().c_str(), strErrMsg.c_str());
        C2C_WW_LOG_LAST_ERR_LOG(strErrMsg);
        return dwRet;
    }

    if(dwExistRecordCount < m_dwMaxRecordNumPerArea || 
            (dwExistRecordCount == m_dwMaxRecordNumPerArea && IsShipTypeAreaLocusRowExist(rCntlInfo, oShipTypeAreaLocusDo,strErrMsg)))
    {
        dwRet = _UpdateShipTypeAreaLocusRowInDB(rCntlInfo, oShipTypeAreaLocusDo, strErrMsg);

        if(dwRet != 0)
        {
            C2C_WW_LOG_ERR(dwRet, "_UpdateShipTypeAreaLocusRowInDB Failed! CmdId:%u strMachineKey:%s strSource:%s dwSceneId:%u,DumpFilter:%s errMsg:%s",
                     rCntlInfo.getCmdId(), strMachineKey.c_str(), strSource.c_str(), dwSceneId, oss.str().c_str(), strErrMsg.c_str());
            C2C_WW_LOG_LAST_ERR_LOG(strErrMsg);
            return dwRet;
        }

        C2C_WW_LOG("_UpdateShipTypeAreaLocusRowInDB Success!  CmdId:%u strMachineKey:%s strSource:%s dwSceneId:%u,DumpFilter:%s ",
                     rCntlInfo.getCmdId(), strMachineKey.c_str(), strSource.c_str(), dwSceneId, oss.str().c_str());
        

        //删cache
        int iCacheRetCode = TMEM_CACHE_OP->DelData(_GetTmemKey(oShipTypeAreaLocusDo.GetShipType(), oShipTypeAreaLocusDo.GetShipTypeLocusGbAreaid()), m_dwTmemBid);
        if(iCacheRetCode != 0)
        {
            strErrMsg = "ShipTypeAreaLocusRowSync DELETE TMEM  failed!";
            strErrMsg += TMEM_CACHE_OP->GetLastErrMsg();

            C2C_WW_LOG_ERR(iCacheRetCode, "ShipTypeAreaLocusRowSync DELETE TMEM  failed!  ShipType[%u] GbAreaId[%u] DBRole[%s] DBTable[%s] ErrMsg[%s]",
                           oShipTypeAreaLocusDo.GetShipType(), oShipTypeAreaLocusDo.GetShipTypeLocusGbAreaid(), DAO_GIS_ERP_ROLE_NAME, GIS_TABLE_SHIPTYPE_AREA_LOCUS, strErrMsg.c_str());

        }

        //重建cache
        erp::gis::ddo::CShipTypeAreaLocusDoList oShipTypeAreaLocusDoList;
        if(_GetMapCoverLocusListFromDB(rCntlInfo, oShipTypeAreaLocusDo.GetShipType(), oShipTypeAreaLocusDo.GetShipTypeLocusGbAreaid(), oWTimeElf, oShipTypeAreaLocusDoList, strErrMsg) != 0)
        {
            C2C_WW_LOG_ERR(dwRet, " Build cache After delete cache Failed! CmdId:%u strMachineKey:%s strSource:%s dwSceneId:%u,dwshiptype:%u, dwdestgbid:%u errMsg:%s",
                     rCntlInfo.getCmdId(), strMachineKey.c_str(), strSource.c_str(), dwSceneId, oShipTypeAreaLocusDo.GetShipType(), oShipTypeAreaLocusDo.GetShipTypeLocusGbAreaid(),strErrMsg.c_str());
        }
     }
    else
    {
        std::stringstream oss;
        oss << "Record Count Exceed Max Value.dwShipType: " << oShipTypeAreaLocusDo.GetShipType() << " dwGbAreaId " << oShipTypeAreaLocusDo.GetShipTypeLocusGbAreaid() ;
        strErrMsg =  oss.str();
        ItilAlarm(strErrMsg);
        return erp::comm::ERR_ERP_DAOGISERP_LOCUS_RECORD_COUNT_EXCEED_MAX_VALUE;
    }

	return dwRet;
}
